package com.mazihao.emos.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateRange;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.mazihao.emos.config.SystemConstants;
import com.mazihao.emos.db.dao.TbCheckinDao;
import com.mazihao.emos.db.dao.TbFaceModelDao;
import com.mazihao.emos.db.dao.TbHolidaysDao;
import com.mazihao.emos.db.dao.TbWorkdayDao;
import com.mazihao.emos.db.pojo.TbCheckin;
import com.mazihao.emos.exception.EmosException;
import com.mazihao.emos.service.CheckinService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

@Service
@Scope("prototype")
@Slf4j
public class CheckinServiceImpl implements CheckinService {

    @Resource
    private SystemConstants constants;

    @Resource
    private TbHolidaysDao holidaysDao;

    @Resource
    private TbWorkdayDao workdayDao;

    @Resource
    private TbCheckinDao tbCheckinDao;

    @Override
    public String validCanCheckIn(int userId, String date) {
        // bool_1 判断是否是节假日
        boolean bool_1 = holidaysDao.searchTodayIsHoliday() != null ? true : false;
        // bool_1 判断是否是工作日
        boolean bool_2 = workdayDao.searchTodayIsWorkday() != null ? true : false;
        String type = "工作日";
        if (DateUtil.date().isWeekend()) {
            type = "节假日";
        }
        if (bool_1) {
            type = "节假日";
        }
        if (bool_2) {
            type = "工作日";
        }
        // 节假日的返回值
        if ("节假日".equals(type)) {
            return "节假日不需要考勤";
        } else {
            // 判断为工作日
            // 今天的日期
            DateTime now = DateUtil.date();
            // 今天上班考勤开始时间
            String start = DateUtil.today() + " " + constants.attendanceStartTime;
            // 今天上班考勤结束时间
            String end = DateUtil.today() + " " + constants.attendanceEndTime;
            // 将字符串转成日期类型
            DateTime attendanceStart = DateUtil.parse(start);
            DateTime attendanceEnd = DateUtil.parse(end);

            // 如果现在的时间在考情开始时间之前,则返回没有到上班考勤开始时间
            if (now.isBefore(attendanceStart)) {
                return "没有到上班考勤开始时间";
            }
            // 如果现在的时间在考情结束时间之后,则返回已经超过上班考勤结束时间
            else if (now.isAfter(attendanceEnd)) {
                return "已经超过上班考勤结束时间";
            }
            // 如果现在的时间在考情开始时间之后,则返回可以考勤
            else {
                HashMap map = new HashMap<>();
                map.put("userId", userId);
                map.put("date", date);
                map.put("start", start);
                map.put("end", end);
                // 判断今天是否已经考勤
                boolean bool = tbCheckinDao.haveCheckin(map) != null ? true : false;
                return bool ? "今日已考勤" : "可以考勤";
            }
        }
    }

    @Override
    public void checkin(HashMap param) {
        // 判断签到
        // 当前时间
        Date date1 = DateUtil.date();
        // 上班签到时间
        Date date2 = DateUtil.parse(DateUtil.today() + " " + constants.attendanceStartTime);
        // 下班签到时间
        Date date3 = DateUtil.parse(DateUtil.today() + " " + constants.attendanceEndTime);
        int status = 1;

        if (date1.compareTo(date2) <= 0) {
            // 正常签到
            status = 1;
        } else if (date1.compareTo(date2) > 0 && date1.compareTo(date3) <= 0) {
            // 迟到签到
            status = 2;
        }
        // 查询签到人的人脸模型数据
        int userId = (Integer) param.get("userId");
//        String faceModel = tbFaceModelDao.searchFaceModel(userId);
//        if (faceModel == null) {
//            throw new EmosException("人脸模型数据不存在");
//        } else {
//            String path = (String) param.get("path");
//            HttpRequest request = HttpUtil.createPost(checkinUrl);
//            request.form("photo", FileUtil.file(path), "targetModel", faceModel);
//            HttpResponse response = request.execute();
//            if (response.getStatus() != 200) {
//                log.error("人脸识别服务异常");
//                throw new EmosException("人脸识别服务异常");
//            }
//            String body = response.body();
//            if ("无法识别出人脸".equals(body) || "照片中存在多张人脸".equals(body)) {
//                throw new EmosException(body);
//            } else if ("False".equals(body)) {
//                throw new EmosException("签到无效,非本人签到");
//            } else if ("True".equals(body)) {
        // 保存签到记录
        String address = (String) param.get("address");
        String country = (String) param.get("country");
        String province = (String) param.get("province");
        String city = (String) param.get("city");
        String district = (String) param.get("district");

        TbCheckin entity = new TbCheckin();
        entity.setUserId(userId);
        entity.setAddress(address);
        entity.setCity(city);
        entity.setDistrict(district);
        entity.setProvince(province);
        entity.setStatus((byte) status);
        entity.setCountry(country);
        entity.setDate(DateUtil.today());
        entity.setCreateTime(date1);
        tbCheckinDao.insert(entity);
    }

    /**
     * 查询用户当天的考勤情况
     * @param userId
     * @return map对象
     */
    @Override
    public HashMap searchTodayCheckin(int userId) {
        return tbCheckinDao.searchTodayCheckin(userId);
    }

    /**
     * 查询用户考勤天数
     * @param userId
     * @return 考勤天数
     */
    @Override
    public long searchCheckinDays(int userId) {
        return tbCheckinDao.searchCheckinDays(userId);
    }

    /**
     * 根据给定的日期范围和参数，搜索每周的考勤情况。
     *
     * @param param 包含起始日期（startDate）和结束日期（endDate）的 HashMap，可能还有其他考勤相关参数。
     * @return 包含每一天考勤状态、日期类型（工作日、节假日或周末）、中文星期的 ArrayList。
     */
    @Override
    public ArrayList<HashMap> searchWeekCheckin(HashMap param) {
        // 获取该周的考勤记录列表
        ArrayList<HashMap> checkinList = tbCheckinDao.searchWeekCheckin(param);

        // 获取在指定日期范围内的节假日列表
        ArrayList<String> holidayList = holidaysDao.searchHolidaysInRange(param);

        // 获取在指定日期范围内的调休日列表（工作日）
        ArrayList<String> workdayList = workdayDao.searchWorkdayInRange(param);

        // 解析起始和结束日期，并生成日期范围
        DateTime startDate = DateUtil.parseDate(param.get("startDate").toString());
        DateTime endDate = DateUtil.parseDate(param.get("endDate").toString());
        DateRange range = DateUtil.range(startDate, endDate, DateField.DAY_OF_MONTH);

        // 用于存储每一天的考勤状态和相关信息
        ArrayList<HashMap> list = new ArrayList<>();

        // 遍历日期范围内的每一天，逐个判断并设置考勤状态
        range.forEach(one -> {
            String date = one.toString("yyyy-MM-dd");  // 获取当天的日期字符串
            String type = "工作日";  // 默认为工作日

            // 如果是周末，则类型为“周末”
            if (one.isWeekend()) {
                type = "工作日";
            }

            // 如果是节假日，则类型为“节假日”
            if (holidayList != null && holidayList.contains(date)) {
                type = "节假日";
            }
            // 如果是调休日，则类型为“工作日”
            else if (workdayList != null && workdayList.contains(date)) {
                type = "工作日";
            }

            String status = "";  // 默认为空，即无考勤状态

            // 如果是工作日并且当前日期不晚于今天，则初始化为“缺勤”
            if ("工作日".equals(type) && DateUtil.compare(one, DateUtil.date()) <= 0) {
                status = "缺勤";
                boolean flag = false;

                // 检查考勤列表中是否有当天的记录
                for (HashMap<String, String> map : checkinList) {
                    if (map.containsValue(date)) {
                        status = map.get("status");  // 若有记录，则获取考勤状态
                        break;
                    }
                }

                DateTime endTime = DateUtil.parse(DateUtil.today() + " " + constants.attendanceEndTime);
                DateTime endWorkTime = DateUtil.parse(DateUtil.today() + " " + constants.attendanceTime);
                String today = DateUtil.today();
                // 如果当天是今天且当前时间还未到上班时间，则状态为正常
                if (date.equals(today) && DateUtil.date().isBefore(endWorkTime) && !flag) {
                    status = "正常";
                }
                // 如果当天是今天且当前时间还已过到上班时间但当前时间还未到考勤结束时间，则状态为迟到
                else if (date.equals(today) && DateUtil.date().isAfter(endWorkTime) && DateUtil.date().isBefore(endTime) && !flag) {
                    status = "迟到";
                }
            }

            // 创建一个 HashMap 存储当天的日期、状态、类型、以及星期几
            HashMap map = new HashMap();
            map.put("date", date);
            map.put("status", status);
            map.put("type", type);
            map.put("day", one.dayOfWeekEnum().toChinese("周"));  // 获取中文的星期几
            list.add(map);  // 将该天的记录加入结果列表
        });
        // 返回包含日期和考勤状态的列表
        return list;
    }

    @Override
    public ArrayList<HashMap> searchMonthCheckin(HashMap param) {
        return this.searchWeekCheckin(param);
    }


}
